package com.itheima.stock.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.stock.common.domain.*;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.*;
import com.itheima.stock.service.StockService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.vo.resp.PageResult;
import com.itheima.stock.vo.resp.R;
import com.itheima.stock.vo.resp.ResponseCode;
import jdk.nashorn.internal.ir.LiteralNode;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service("stockService")
@Slf4j
public class StockServiceImpl implements StockService {

    @Autowired
    private StockBusinessMapper stockBusinessMapper;

    // 存放有国内大盘的标记
    @Autowired
    private StockInfoConfig stockInfoConfig;
    // 大盘mapper对象
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    // 板块mapper对象
    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;

    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;

    @Override
    public R<List<StockBlockDomain>> sectorAllLimit() {
        //1.调用mapper接口获取数据
        List<StockBlockDomain> infos = stockBlockRtInfoMapper.sectorAllLimit();
        //2.组装数据
        if (CollectionUtils.isEmpty(infos)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(infos);
    }

    @Override
    public R<List<OuterMarketDomain>> outerIndexAll() {
        List<String> outerIds = stockInfoConfig.getOuter();
        Date lDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();

        //实时数据获取
        String lDates = new SimpleDateFormat("yyyyMMddHHmmss").format(lDate);
        lDate = DateTime.parse(lDates, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        //3.调用mapper查询指定日期下对应的国外大盘数据
        List<OuterMarketDomain> list=stockMarketIndexInfoMapper.selectOutByIdsAndDate(outerIds,lDate);
        //组装响应的额数据
        if (CollectionUtils.isEmpty(list)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(list);
    }

    @Override
    public R<List<StockUpdownDomain>> stockIncreaseLimit() {
        Date curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
//        String mockStr="2021-12-27 09:47:00";
//        curDateTime = DateTime.parse(mockStr, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
//        String curDateTimes = new SimpleDateFormat("yyyyMMddHHmmss").format(curDateTime);
//        curDateTime = DateTime.parse(curDateTimes, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        List<StockUpdownDomain> infos = stockRtInfoMapper.stockIncreaseLimit(curDateTime);

        if (CollectionUtils.isEmpty(infos)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }

        return R.ok(infos);
    }

    @Override
    public R<PageResult<StockUpdownDomain>> stockPage(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);

        List<StockUpdownDomain> infos = stockRtInfoMapper.stockAll();
        if (CollectionUtils.isEmpty(infos)) {
            return R.error("暂无数据");
        }

        PageInfo<StockUpdownDomain> listPageInfo = new PageInfo<>(infos);

        PageResult<StockUpdownDomain> pageResult = new PageResult<>(listPageInfo);

        return R.ok(pageResult);
    }

    @Override
    public R<Map> upDownCount() {
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date curTime = curDateTime.toDate();
        Date openTime = DateTimeUtil.getOpenDate(curDateTime).toDate();
//        String curTimeStr = "20220106142500";
//        String openTimeStr = "20220106092500";
//
//        curTime = DateTime.parse(curTimeStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
//        openTime = DateTime.parse(openTimeStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String curTimes = new SimpleDateFormat("yyyyMMddHHmmss").format(curTime);
        curTime = DateTime.parse(curTimes, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String openTimes = new SimpleDateFormat("yyyyMMddHHmmss").format(openTime);
        openTime = DateTime.parse(openTimes, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        List<Map> upCount = stockRtInfoMapper.upDownCount(curTime, openTime, 1);
        List<Map> downCount = stockRtInfoMapper.upDownCount(curTime, openTime, 0);

        HashMap<String, List<Map>> info = new HashMap<>();
        info.put("upList", upCount);
        info.put("downList", downCount);

        return R.ok(info);
    }

    @Override
    public void stockExport(HttpServletResponse response, Integer page, Integer pageSize) {
        try {
            //1.设置响应数据的类型:excel
            response.setContentType("application/vnd.ms-excel");
            //2.设置响应数据的编码格式
            response.setCharacterEncoding("utf-8");
            //3.设置默认的文件名称
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("stockRt", "UTF-8");
            //设置默认文件名称
            response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xlsx");
            //4.分页查询股票数据
            PageHelper.startPage(page,pageSize);
            List<StockUpdownDomain> infos = this.stockRtInfoMapper.stockAll();
            List<StockExcelDomain> excelDomains = infos.stream().map(info -> {
                StockExcelDomain domain=new StockExcelDomain();
                BeanUtils.copyProperties(info,domain);
                return domain;
            }).collect(Collectors.toList());
            //5.导出
            EasyExcel.write(response.getOutputStream(),StockExcelDomain.class).sheet("股票数据").doWrite(excelDomains);
        } catch (IOException e) {
            log.info("股票excel数据导出异常，当前页：{}，每页大小：{}，异常信息：{}",page,pageSize,e.getMessage());
        }
    }

    @Override
    public R<Map> stockTradeVol4InnerMarket() {
        //1.获取最近的股票交易日时间，精确到分钟 T交易日
        DateTime tDate = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date tDateTime = tDate.toDate();
        //对应的开盘时间
        Date tOpenTime = DateTimeUtil.getOpenDate(tDate).toDate();

//        String tDateStr="20220103143000";
//        tDateTime = DateTime.parse(tDateStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
//        //mock-data
//        String openDateStr="20220103093000";
//        tOpenTime = DateTime.parse(openDateStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        String tDateTimes = new SimpleDateFormat("yyyyMMddHHmmss").format(tDateTime);
        tDateTime = DateTime.parse(tDateTimes, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String tOpenTimes = new SimpleDateFormat("yyyyMMddHHmmss").format(tOpenTime);
        tOpenTime = DateTime.parse(tOpenTimes, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        //获取T-1交易日
        DateTime preTDate = DateTimeUtil.getPreviousTradingDay(tDate);
        Date preTTime = preTDate.toDate();
        Date preTOpenTime=DateTimeUtil.getOpenDate(preTDate).toDate();

//        String preTStr="20220102143000";
//        preTTime = DateTime.parse(preTStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
//        //mock-data
//        String openDateStr2="20220102093000";
//        preTOpenTime= DateTime.parse(openDateStr2, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        String preTTimes = new SimpleDateFormat("yyyyMMddHHmmss").format(preTTime);
        preTTime = DateTime.parse(preTTimes, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String preTOpenTimes = new SimpleDateFormat("yyyyMMddHHmmss").format(preTOpenTime);
        preTOpenTime = DateTime.parse(preTOpenTimes, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        //2.获取T日的股票大盘交易量统计数据
        List<Map> tData=stockMarketIndexInfoMapper.stockTradeVolCount(stockInfoConfig.getInner(),tOpenTime,tDateTime);
        //3.获取T-1的数据
        List<Map> preTData=stockMarketIndexInfoMapper.stockTradeVolCount(stockInfoConfig.getInner(),preTOpenTime,preTTime);
        //4.组装数据
        HashMap<String, List<Map>> data = new HashMap<>();
        data.put("volList",tData);
        data.put("yesVolList",preTData);
        return R.ok(data);
    }

    @Override
    public R<Map> stockUpDownScopeCount() {
        //1.获取当前时间下最近的一个股票交易时间 精确到秒
        DateTime avlDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date avlDate = avlDateTime.toDate();
//        //后续修改
//        String  mockDate="20220106095500";
//        avlDate = DateTime.parse(mockDate, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        String avlDates = new SimpleDateFormat("yyyyMMddHHmmss").format(avlDate);
        avlDate = DateTime.parse(avlDates, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();


        //2.查询
        List<Map> maps=stockRtInfoMapper.stockUpDownScopeCount(avlDate);
        //获取去股票涨幅区间的集合
        List<String> upDownRange = stockInfoConfig.getUpDownRange();
        //将list集合下的字符串映射成Map对象
        List<Map> orderMap = upDownRange.stream().map(key -> {
            Optional<Map> title = maps.stream().filter(map -> key.equals(map.get("title"))).findFirst();
            //判断对应的map是否存在
            Map tmp = null;
            if (title.isPresent()) {
                tmp = title.get();
            } else {
                tmp = new HashMap();
                tmp.put("title", key);
                tmp.put("count", 0);
            }
            return tmp;
        }).collect(Collectors.toList());
        //3.组装data
        HashMap<String, Object> data = new HashMap<>();
        data.put("time",avlDateTime.toString("yyyy-MM-dd HH:mm:ss"));
        data.put("infos",orderMap);
        //返回响应数据
        return R.ok(data);
    }

    @Override
    public R<List<Stock4MinuteDomain>> stockScreenTimeSharing(String code) {
        //1.获取最近有效的股票交易时间
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //获取当前日期
        Date curDate = curDateTime.toDate();
        //获取当前日期对应的开盘日期
        Date openDate = DateTimeUtil.getOpenDate(curDateTime).toDate();
//        //后续修改
//        String mockDate="20220106142500";
//        curDate=DateTime.parse(mockDate, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
//        String openDateStr="20220106093000";
//        openDate=DateTime.parse(openDateStr, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        String curDates = new SimpleDateFormat("yyyyMMddHHmmss").format(curDate);
        curDate = DateTime.parse(curDates, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String openDates = new SimpleDateFormat("yyyyMMddHHmmss").format(openDate);
        openDate = DateTime.parse(openDates, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        List<Stock4MinuteDomain> maps= stockRtInfoMapper.stockScreenTimeSharing(code,openDate,curDate);
        //响应前端
        return R.ok(maps);
    }

    @Override
    public R<List<Stock4EvrDayDomain>> stockCreenDkLine(String code) {
        //获取当前日期前推20天
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //当前时间节点
        Date curTime = curDateTime.toDate();
        //前推20
        Date pre20Day = curDateTime.minusDays(20).toDate();

        String curTimes = new SimpleDateFormat("yyyyMMddHHmmss").format(curTime);
        curTime = DateTime.parse(curTimes, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
        String pre20Days = new SimpleDateFormat("yyyyMMddHHmmss").format(pre20Day);
        pre20Day = DateTime.parse(pre20Days, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        List<Stock4EvrDayDomain> infos = stockRtInfoMapper.stockCreenDkLine(code, pre20Day, curTime);
        return R.ok(infos);
    }

    /**
     * 联想查询
     * @param
     * @return
     */
    @Override
    public R<List<StockCodeLenovo>> stockNameByCode(String searchStr) {
        if (searchStr == null) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }

        List<StockCodeLenovo> infos = stockBusinessMapper.getStockName(searchStr);
        return R.ok(infos);
    }

    @Override
    public R<StockDescribe> stockDescribe(String code) {
        if (code == null) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }

        StockDescribe infos = stockBusinessMapper.getDescribe(code);
        return R.ok(infos);
    }

    /**
     * 个股最新分时详情
     * @param code
     * @return
     */
    @Override
    public R<StockNewTimeShare> getStockNew(String code) {
        if (code == null) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }

        Date lDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();

        StockNewTimeShare infos = stockRtInfoMapper.getNewTimeShare(code,lDate);
        return R.ok(infos);
    }

    /**
     * 个股实时交易流水
     * @param code
     * @return
     */
    @Override
    public R<List<StockTimeTransaction>> getStockTimeTransaction(String code) {

        List<StockTimeTransaction> infos = stockRtInfoMapper.getTimeTransaction(code);
        return R.ok(infos);

    }

    /**
     * 个股周K线
     * @param code
     * @return
     */
    @Override
    public R<List<StockWeekK>> stockWeekK(String code) {
        //获取当前日期
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());

        //当前时间节点
        Date curTime = curDateTime.toDate();

        //前推至周一
        Date pre7Day = curDateTime.minusDays(4).toDate();


//        String curTimes = new SimpleDateFormat("yyyyMMddHHmmss").format(curTime);
//        curTime = DateTime.parse(curTimes, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();
//        String pre7Days = new SimpleDateFormat("yyyyMMddHHmmss").format(pre7Day);
//        pre7Day = DateTime.parse(pre7Days, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();

        List<StockWeekK> infos = stockRtInfoMapper.stockCreenWeekKLine(code, pre7Day, curTime);
        return R.ok(infos);
    }

    @Override
    public R<List<InnerMarketDomain>> innerIndexAll() {
        //1.获取国内大盘的id集合
        List<String> innerIds = stockInfoConfig.getInner();
        //2.获取最近最新的股票有效交易日
        Date lDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
//
//        String lDates = new SimpleDateFormat("yyyyMMddHHmmss").format(lDate);
//        lDate = DateTime.parse(lDates, DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate();



        //3.调用mapper查询指定日期下对应的国内大盘数据
        List<InnerMarketDomain> list=stockMarketIndexInfoMapper.selectByIdsAndDate(innerIds,lDate);
        //组装响应的额数据
        if (CollectionUtils.isEmpty(list)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(list);
    }

    @Override
    public List<StockBusiness> getAllStockBusiness() {
        return stockBusinessMapper.getAll();
    }
}
